//********************************************************************************************//
//*****************************************微扰法*********************************************//
//*******************************************************************************************//

//*********** Structure Definition ********//

typedef struct {
	float32  Ipv;                // 当前光伏板电流
	float32  Vpv;                // 当前光伏板电压
	float32  DeltaPmin;          // 最小功率变化阈值
	float32  MaxVolt;            // 最大电压限制
	float32  MinVolt;            // 最小电压限制
	float32  Stepsize;           // 电压步长
	float32  VmppOut;            // 输出的最大功率点电压
	float32  DeltaP;             // 当前功率与上一次功率的差值
	float32  PanelPower;         // 当前光伏板功率
	float32  PanelPower_Prev;    // 上一次光伏板功率
	int16 mppt_enable;           // 是否启用MPPT算法
	int16 mppt_first;            // 是否是第一次运行MPPT算法
} MPPT_PNO_F;
 
//*********** Structure Init Function ****//
void MPPT_PNO_F_init(MPPT_PNO_F *v)
{
	v->Ipv=0;
	v->Vpv=0;
	v->DeltaPmin=(0.00001);
	v->MaxVolt=(0.9);
	v->MinVolt=0;
	v->Stepsize=(0.002);
	v->VmppOut=0;
	v->DeltaP=0;
	v->PanelPower=0;
	v->PanelPower_Prev=0;
	v->mppt_enable=1;
	v->mppt_first=1;
}
 
//*********** Function Definition ********//
void MPPT_PNO_F_FUNC(MPPT_PNO_F *v)
{
    if (v->mppt_enable == 1)  // 检查是否启用MPPT算法
    {
        if (v->mppt_first == 1)  // 如果是第一次运行MPPT算法
        {
            // 初始化最大功率点电压（VmppOut），设置为当前电压减去一个初始偏移量
            v->VmppOut = v->Vpv - (0.02);  
            v->mppt_first = 0;  // 标记为非首次运行
            // 将当前功率设置为上一次功率（初始值）
            v->PanelPower_Prev = v->PanelPower;  
        }
        else  // 非首次运行
        {
            // 计算当前光伏板的功率（P = V * I）
            v->PanelPower = (v->Vpv * v->Ipv);
            // 计算当前功率与上一次功率的差值
            v->DeltaP = v->PanelPower - v->PanelPower_Prev;

            // 根据功率变化调整电压
            if (v->DeltaP > v->DeltaPmin)  // 如果功率增加超过阈值
            {
                // 增加电压步长，向最大功率点靠近
                v->VmppOut = v->Vpv + v->Stepsize;
            }
            else
            {
                // 如果功率减少超过阈值
                if (v->DeltaP < -v->DeltaPmin)
                {
                    // 反转步长方向（负步长），尝试反向调整
                    v->Stepsize = -v->Stepsize;
                    // 调整电压
                    v->VmppOut = v->Vpv + v->Stepsize;
                }
            }

            // 更新上一次功率为当前功率，为下一次迭代做准备
            v->PanelPower_Prev = v->PanelPower;
        }

        // 限制输出电压范围，确保不超过设定的最小和最大电压
        if (v->VmppOut < v->MinVolt) v->VmppOut = v->MinVolt;
        if (v->VmppOut > v->MaxVolt) v->VmppOut = v->MaxVolt;
    }
}


//*******************************************************************************************//
//*************************************电导增量法*********************************************//
//*******************************************************************************************//
typedef struct {
	float32  Ipv;                // 当前光伏板电流
	float32  Vpv;                // 当前光伏板电压
	float32  IpvH;               // 电流上限容差
	float32  IpvL;               // 电流下限容差
	float32  VpvH;               // 电压上限容差
	float32  VpvL;               // 电压下限容差
	float32  MaxVolt;            // 最大电压限制
	float32  MinVolt;            // 最小电压限制
	float32  Stepsize;           // 电压步长
	float32  VmppOut;            // 输出的最大功率点电压
	float32  Cond;               // 当前电导
	float32  IncCond;            // 增量电导
	float32  DeltaV;             // 电压变化量
	float32  DeltaI;             // 电流变化量
	float32  VpvOld;             // 上一次电压值
	float32  IpvOld;             // 上一次电流值
	float32  StepFirst;          // 第一次运行时的初始步长
	int16 mppt_enable;           // 是否启用MPPT算法
	int16 mppt_first;            // 是否是第一次运行MPPT算法
} MPPT_INCC_F;

void MPPT_INCC_F_init(MPPT_INCC_F *v)
{
	v->Ipv = 0;
	v->Vpv = 0;
	v->IpvH = (1.65);            
	v->IpvL = 0;                 
	v->VpvH = 0;                 
	v->VpvL = 0;                 
	v->MaxVolt = 0;              
	v->MinVolt = 0;              
	v->Stepsize = 0;             
	v->VmppOut = 0;              
	v->Cond = 0;                 
	v->IncCond = 0;              
	v->DeltaV = 0;               
	v->DeltaI = 0;               
	v->VpvOld = 0;               
	v->IpvOld = 0;               
	v->StepFirst = (0.02);       
	v->mppt_enable = 1;          
	v->mppt_first = 1;           
}

void MPPT_INCC_F_FUNC(MPPT_INCC_F *v)
{
	if (v->mppt_enable == 1)
	{
		if (v->mppt_first == 1)
		{
			v->VmppOut = v->Vpv - v->StepFirst;   // 初始化最大功率点电压
			v->VpvOld = v->Vpv;                   // 保存当前电压
			v->IpvOld = v->Ipv;                   // 保存当前电流
			v->mppt_first = 0;                    // 标记为非首次运行
		}
		else
		{
			v->DeltaV = v->Vpv - v->VpvOld;       // 计算电压变化量
			v->DeltaI = v->Ipv - v->IpvOld;       // 计算电流变化量

			// 如果电压变化量为零
			if (v->DeltaV == 0)
			{
				// 如果电流变化量不为零，说明处于最大功率点附近
				if (v->DeltaI != 0)
				{
					// 根据电流变化方向调整电压
					if (v->DeltaI > 0)
					{
						v->VmppOut = v->Vpv + v->Stepsize;  // 增加电压
					}
					else
					{
						v->VmppOut = v->Vpv - v->Stepsize;  // 减少电压
					}
				}
			}
			else
			{
				// 计算当前电导和增量电导
				v->Cond = v->Ipv * __einvf32(v->Vpv);          // 当前电导
				v->IncCond = v->DeltaI * __einvf32(v->DeltaV); // 增量电导

				// 如果增量电导不等于当前电导，说明未处于最大功率点
				if (v->IncCond != v->Cond)
				{
					// 根据增量电导与当前电导的关系调整电压
					if (v->IncCond > (-v->Cond))
					{
						v->VmppOut = v->Vpv + v->Stepsize;  // 增加电压
					}
					else
					{
						v->VmppOut = v->Vpv - v->Stepsize;  // 减少电压
					}
				}
			}
			// 更新上一次的电压和电流值
			v->VpvOld = v->Vpv;
			v->IpvOld = v->Ipv;
		}
	}
}
